
import Data.List
import Test.QuickCheck

-------------------------------------------------------------------------
-- test data generators

-- bits

data Bit = O | I
  deriving ( Show, Eq )

instance Arbitrary Bit where
  arbitrary = arbBit

arbBit :: Gen Bit
arbBit = oneof [ return O, return I ]
{-
-- alternatively:
arbBit = frequency [ (2,return O), (1,return I) ]

-- alternatively:
arbBit = elements [ O, I ]

-- alternatively:
arbBit = do x <- choose (0,1 :: Int)
            return (if x == 0 then O else I)
-}

(&) :: Bit -> Bit -> Bit
I & x = x
O & x = x

prop_And x y =
  (x & y) == (y & x)

-- components

type Color = Bit

data Item = Item Int Color Int

instance Arbitrary Item where
  arbitrary =
    do it <- arbitrary
       cl <- arbitrary
       n  <- choose (0,10)
       return (Item it cl n)

data Room = Room Int [Item]

instance Arbitrary Room where
  arbitrary =
    do ds <- arbitrary
       xs <- arbitrary
       return (Room ds xs)

-- ordered lists

ordered :: Ord a => [a] -> Bool
ordered []       = True
ordered [x]      = True
ordered (x:y:xs) = x <= y && ordered (y:xs)

prop_Insert :: Int -> [Int] -> Property
prop_Insert x xs =
  ordered xs ==>
    ordered (insert x xs)

-- a specialized type for ordered lists

data OrderedList a = Ordered [a]

-- and a generator for it
instance (Ord a, Arbitrary a) => Arbitrary (OrderedList a) where
  arbitrary =
    do xs <- arbitrary
       return (Ordered (sort xs))
     
prop_Insert' :: Int -> OrderedList Int -> Bool
prop_Insert' x (Ordered xs) =
  ordered (insert x xs)

-------------------------------------------------------------------------
